﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Util;


namespace iCalSync
{
    class GCalConnect
    {
        public static CalendarService getCalServ()
        {
            var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
            provider.ClientIdentifier = "360648465177.apps.googleusercontent.com";
            provider.ClientSecret = "RzUzMXPyQmKKe_hpuLKUCDdb";
            var auth2 = new OAuth2LeggedAuthenticator(provider.ClientIdentifier, provider.ClientSecret, "christophe", "demay.me");
            /*var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthentication);
                       
            auth.LoadAccessToken();
            
            var service = new CalendarService(auth);*/
            var service = new CalendarService(auth2);
            return service;
        }

        private static IAuthorizationState GetAuthentication(NativeApplicationClient arg)
        {
            IAuthorizationState state = new AuthorizationState(new[] { CalendarService.Scopes.Calendar.GetStringValue() });
           
            state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);

            ConnectForm frm = new ConnectForm();
            frm.authUri = arg.RequestUserAuthorization(state);
            frm.ShowDialog();
            
            return arg.ProcessUserAuthorization(frm.authCode, state);
        }
     }
    
    
    class GCalClient
    {
        public Dictionary<string, Event> gEvents { get; set; }

        public void ReadEvents(IcsFile icsFile, ref CalendarService service, ref BackgroundWorker bg)
        {
            string CalId = Properties.Settings.Default.calId;
            string Tz = service.Calendars.Get(CalId).Fetch().TimeZone;
            var lst = service.Events.List(CalId);
            lst.TimeMin = icsFile.Debut.ToString("yyyy-MM-ddTHH:mm:ssZ");
            lst.TimeMax = icsFile.Fin.ToString("yyyy-MM-ddTHH:mm:ssZ");
            lst.TimeZone = Tz;
            gEvents = new Dictionary<string, Event>();
            do
            {
                if (bg.CancellationPending)
                    if (System.Windows.Forms.MessageBox.Show("Arrêter la synchronisation ?", "Arrêt", System.Windows.Forms.MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
                        return;
                foreach (Event ev in lst.Fetch().Items)
                {
                    gEvents.Add(ev.ICalUID, ev);
                    bg.ReportProgress(0, "Lecture du calendrier Google");
                }
            } while (!String.IsNullOrEmpty(lst.PageToken));
        }

        public void UpdateEvents(IcsFile icsFile, ref CalendarService service, ref BackgroundWorker bg)
        {
            ReadEvents(icsFile, ref service, ref bg);
            string CalId = Properties.Settings.Default.calId;
            string Tz = service.Calendars.Get(CalId).Fetch().TimeZone;
            CultureInfo Ci = new CultureInfo("fr-FR",false);
            decimal nb = icsFile.Events.Count;
            decimal i = 0;
            foreach (KeyValuePair<string, IcsEvent> evt in icsFile.Events)
            {
                if (bg.CancellationPending)
                    if (System.Windows.Forms.MessageBox.Show("Arrêter la synchronisation ?", "Arrêt", System.Windows.Forms.MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
                        return;
                Event e = (Event)evt.Value;
                e.Start.TimeZone = Tz;
                e.End.TimeZone = Tz;
                if (gEvents.ContainsKey(evt.Key))
                {
                    e.ETag = gEvents[evt.Key].ETag;
                    e.Sequence = gEvents[evt.Key].Sequence + 1;
                    Event b = service.Events.Update(e, CalId, gEvents[evt.Key].Id).Fetch();
                }
                else
                {
                    Event ev = GetId(e.ICalUID, CalId, ref service);
                    if (ev == null)
                    {
                        Event b = service.Events.Insert(e, CalId).Fetch();
                    }
                    else
                    {
                        e.ETag = ev.ETag;
                        e.Sequence = ev.Sequence + 1;
                        e.Attendees = ev.Attendees;
                        Event b = service.Events.Update(e, CalId, ev.Id).Fetch();
                    }

                    //Event b = service.Events.Insert(e, CalId).Fetch();
                }
                bg.ReportProgress((int)((i++ / nb) * 100), "Mise à jour de :" + e.Summary);
            }
            nb = gEvents.Count;
            i = 0;
            foreach (KeyValuePair<string, Event> evt in gEvents)
            {
                if (bg.CancellationPending)
                    if (System.Windows.Forms.MessageBox.Show("Arrêter la synchronisation ?", "Arrêt", System.Windows.Forms.MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
                        return;
                Event e = (Event)evt.Value;
                if (!icsFile.Events.ContainsKey(evt.Key))
                {
                    string b = service.Events.Delete(CalId, e.Id).Fetch();
                }
                bg.ReportProgress((int)((i++ / nb) * 100), "Suppression:" + e.Summary);
            }
        }


        public static void CreateEvents(IcsFile icsFile, ref CalendarService service, ref BackgroundWorker bg)
        {
            string CalId = Properties.Settings.Default.calId;
            string Tz = service.Calendars.Get(CalId).Fetch().TimeZone;
            decimal nb = icsFile.Events.Count;
            decimal i = 0;
            foreach (KeyValuePair<string,IcsEvent> evt in icsFile.Events)
            {
                if (bg.CancellationPending)
                    if (System.Windows.Forms.MessageBox.Show("Arrêter la synchronisation ?", "Arrêt", System.Windows.Forms.MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.OK)
                        return;
                Event e = (Event)evt.Value;
                e.Start.TimeZone = Tz;
                e.End.TimeZone = Tz;
                Event ev = GetId(e.ICalUID, CalId, ref service);
                if (ev == null)
                {
                    Event b = service.Events.Insert(e, CalId).Fetch();
                }
                else
                {
                    e.ETag = ev.ETag;
                    e.Sequence = ev.Sequence+1;
                    Event b = service.Events.Update(e, CalId, ev.Id).Fetch();
                }
                bg.ReportProgress((int)((i++/nb)*100), "Mise à jour de :" + e.Summary);
            }
            return;
        }

        public static Dictionary<string, string> getAllCals(ref CalendarService service)
        {
            IList<CalendarListEntry> Cals = service.CalendarList.List().Fetch().Items;
            Dictionary<string, string> CalList = new Dictionary<string, string>();
            foreach (CalendarListEntry c in Cals)
            {
                if (c.AccessRole!="reader")
                    CalList.Add(c.Summary, c.Id);
            }
            return CalList;
        }

        private static Event GetId(string Uid, String CalId, ref CalendarService service)
        {
            Event id = null;
            var a = service.Events.List(CalId);
            a.ICalUID = Uid;
            a.ShowDeleted = true;
            IList<Event> evts = a.Fetch().Items;
            if (!(evts == null))
                id = evts[0];
            return id;
        }
    }
}
